package cn.com.xy.sms.sdk.db.entity;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.json.JSONObject;

import android.content.ContentValues;
import android.database.Cursor;
import cn.com.xy.sms.sdk.Iservice.OnlineUpdateCycleConfigInterface;
import cn.com.xy.sms.sdk.constant.Constant;
import cn.com.xy.sms.sdk.db.ContactsDBManager;
import cn.com.xy.sms.sdk.db.XyCursor;
import cn.com.xy.sms.sdk.db.base.BaseManager;
import cn.com.xy.sms.sdk.dex.DexUtil;
import cn.com.xy.sms.sdk.log.LogManager;
import cn.com.xy.sms.sdk.util.StringUtils;

/* SDK-428 huangzhiqiang 20160618 start */
public class NumberInfoManager {
    public static final String ID = "id"; // 自增ID
    public static final String NUM = "num"; // 号码
    public static final String RESULT = "result"; // 号码别结果
    public static final String VERSION = "version"; // 版本号
    public static final String LAST_QUERY_TIME = "last_query_time"; // 最近一次数据查询时间
    
    /*IMOO-20 zhaojiangwei 20161221 start */
    public static final String FLAG_T9 = "t9_flag"; //是否支付T9搜索
    /*IMOO-20 zhaojiangwei 20161221 start */

    public static final String TABLE_NAME = "tb_number_info";
    public static final String DROP_TABLE = " DROP TABLE IF EXISTS " + TABLE_NAME;
    public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + ID
            + " INTEGER PRIMARY KEY, " + NUM + " TEXT UNIQUE, " + RESULT + " TEXT, " + VERSION + " TEXT, "
            + FLAG_T9 + " INTEGER DEFAULT 0, " + LAST_QUERY_TIME + " INTEGER DEFAULT 0)";
    
    public static final String CREATE_INDEX_LAST_QUERY_TIME = "CREATE INDEX IDX_" + TABLE_NAME + "_" + LAST_QUERY_TIME
            + " ON " + TABLE_NAME + "(" + LAST_QUERY_TIME + ");";

    public static final int TYPE_REPARSE_NO_NETWORK_NUM_INFO = 1; // 类型-重新识别未联网导致无法查询到号码信息的号码
    public static final int TYPE_REPARSE_INVALID_NUM_INFO = 2; // 类型-重新识别已联网查询过但无号码信息的号码(相同号码24小时内只会重新识别一次)
    public static final int TYPE_REPARSE_EXPIRED_NUM_INFO = 3; // 类型-重新识别已过有效周期的号码信息(有效周期30天)
    public static final int TYPE_UPLOAD_USER_TAG = 4; // 类型-上传用户标记
    
    /*IMOO-20 zhaojiangwei 20161221 start */
    public static final String ADD_COLUMN_T9FLAG = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + FLAG_T9 + " INTEGER DEFAULT '0'";
    /*IMOO-20 zhaojiangwei 20161221 end */
    
    /**
     * 保存用户标记
     * 
     * @param num 号码
     * @param tag 用户标记
     * @param tagType 用户标记类型(1：系统预制类型 2：自定义类型)
     * @param extend
     * @return
     */
    public static JSONObject saveUserTag(String num, String tag, int tagType, Map<String, String> extend) {
        if (StringUtils.isNull(num)) {
            return null;
        }
        try {
            NumberInfo numberInfo = NumberInfoManager.queryByNumAndVersion(num, null);
            if (numberInfo != null) {
                return appendUserTagToDBAndReturnResultFieldJson(numberInfo, tag, tagType);
            } else {
                return insertUserTagToDBAndReturnResultFieldJson(num, tag, tagType);
            }
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumberInfoManager saveUserTag error:", e);
            /*SDK-550 hewengao 20160719 end*/
        }
        return null;
    }

    /**
     * 添加用户标记信息到已有的号码识别结果
     * 
     * @param numberInfo 已有的号码识别结果
     * @param tag 用户标记
     * @param tagType 用户标记类型(1：系统预制类型 2：自定义类型)
     * @return
     * @throws Exception
     */
    private static JSONObject appendUserTagToDBAndReturnResultFieldJson(NumberInfo numberInfo, String tag, int tagType)
            throws Exception {
        if (numberInfo == null || StringUtils.isNull(tag)) {
            return null;
        }

        JSONObject resultJson = null;
        if (!StringUtils.isNull(numberInfo.result)) {
            resultJson = new JSONObject(numberInfo.result);
        } else {
            resultJson = new JSONObject();
        }
        ContentValues userTagContentValues = putUserTagInfoToResultJsonAndCreateUserTagContentValues(resultJson,
                numberInfo.num, tag, tagType, NumberInfo.UPLOAD_STATUS_NO_UPLOAD, numberInfo.version,
                String.valueOf(numberInfo.lastQueryTime));

        if (ContactsDBManager.update(TABLE_NAME, userTagContentValues, NUM + " = ? ", new String[] { numberInfo.num }) > 0) {
            return resultJson;
        }
        return null;
    }

    /**
     * 新增用户标记信息到数据库
     * 
     * @return
     */
    private static JSONObject insertUserTagToDBAndReturnResultFieldJson(String num, String tag, int tagType)
            throws Exception {
        JSONObject resultJson = new JSONObject();
        String version = "";
        String lastQueryTime = String.valueOf(System.currentTimeMillis());
        ContentValues userTagContentValues = putUserTagInfoToResultJsonAndCreateUserTagContentValues(resultJson, num,
                tag, tagType, NumberInfo.UPLOAD_STATUS_NO_UPLOAD, version, lastQueryTime);

        if (ContactsDBManager.insert(TABLE_NAME, userTagContentValues) > 0) {
            return resultJson;
        }
        return null;
    }

    private static ContentValues putUserTagInfoToResultJsonAndCreateUserTagContentValues(JSONObject resultJson,
            String num, String tag, int tagType, int userTagUploadStatus, String version, String lastQueryTime)
            throws Exception {
        if (resultJson == null) {
            return null;
        }
        resultJson.put(NumberInfo.NUM_KEY, num);
        resultJson.put(NumberInfo.USER_TAG_KEY, tag);
        resultJson.put(NumberInfo.USER_TAG_TYPE_KEY, tagType);
        resultJson.put(NumberInfo.USER_TAG_UPLOAD_STATUS_KEY, userTagUploadStatus);
        ContentValues userTagContentValues = BaseManager.getContentValues(null, NUM, num, RESULT,
                resultJson.toString(), VERSION, version, LAST_QUERY_TIME, lastQueryTime);
        return userTagContentValues;
    }

    /**
     * 更新用户标记上传状态
     * 
     * @param num
     * @param uploadStatus 用户标记上传状态(0:未上传 1:已上传)
     * @return
     */
    public static int updateUploadUserTagStatus(String num, int uploadStatus){
        if (StringUtils.isNull(num)) {
            return -1;
        }
        XyCursor xyCursor = null;
        try {
            xyCursor = ContactsDBManager.query(TABLE_NAME, new String[] { RESULT }, NUM + " = ? ",
                    new String[] { num });
            if (xyCursor != null && xyCursor.getCount() > 0 && xyCursor.moveToFirst()) {
                String dbResult = xyCursor.getString(xyCursor.getColumnIndex(RESULT));
                JSONObject dbResultJson = new JSONObject(dbResult);
                dbResultJson.put(NumberInfo.USER_TAG_UPLOAD_STATUS_KEY, uploadStatus);
                return ContactsDBManager.update(TABLE_NAME,
                        BaseManager.getContentValues(null, RESULT, dbResultJson.toString()), NUM + " = ? ",
                        new String[] { num });
            } 
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumberInfoManager updateUploadUserTagStatus error:", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(xyCursor, true);
        }
        return -1;
    }
    
    /**
     * 更新用户标记上传状态
     * 
     * @param nums 需要更新上传状态的号码集合
     * @param uploadStatus 用户标记上传状态(0:未上传 1:已上传)
     * @return
     */
    public static int updateUploadUserTagStatus(Set<String> nums, int uploadStatus) {
        if (nums == null || nums.size() == 0) {
            return -1;
        }
        XyCursor xyCursor = null;
        try {
            int size = nums.size();
            String placeholders = SmsParseRecorder.makePlaceholders(size);
            String whereClause = NUM + " IN(" + placeholders + ")";
            String[] whereArgs = nums.toArray(new String[size]);
            xyCursor = ContactsDBManager.query(TABLE_NAME, new String[] { NUM, RESULT }, whereClause, whereArgs);
            if (xyCursor == null || xyCursor.getCount() == 0) {
                return -1;
            }
            int rs = 0;
            while (xyCursor.moveToNext()) {
                String dbResult = xyCursor.getString(xyCursor.getColumnIndex(RESULT));
                if (!StringUtils.isNull(dbResult)) {
                    String num = xyCursor.getString(xyCursor.getColumnIndex(NUM));
                    JSONObject dbResultJson = new JSONObject(dbResult);
                    dbResultJson.put(NumberInfo.USER_TAG_UPLOAD_STATUS_KEY, uploadStatus);
                    rs += ContactsDBManager.update(TABLE_NAME,
                            BaseManager.getContentValues(null, RESULT, dbResultJson.toString()), NUM + " = ? ",
                            new String[] { num });
                }
            }
            return rs;
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumberInfoManager error:", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(xyCursor, true);
        }
        return -1;
    }
    
    /**
     * 删除用户标记信息
     * 
     * @param num 号码
     * @return
     */
    public static void removeUserTag(String num) {
        if (StringUtils.isNull(num)) {
            return;
        }
        XyCursor xyCursor = null;
        try {
            xyCursor = ContactsDBManager
                    .query(TABLE_NAME, new String[] { RESULT }, NUM + " = ? ", new String[] { num });
            if (xyCursor != null && xyCursor.getCount() > 0 && xyCursor.moveToFirst()) {
                String dbResult = xyCursor.getString(xyCursor.getColumnIndex(RESULT));
                JSONObject dbResultJson = new JSONObject(dbResult);
                removeUserTag(dbResultJson);
                ContactsDBManager.update(TABLE_NAME,
                        BaseManager.getContentValues(null, RESULT, dbResultJson.toString()), NUM + " = ? ",
                        new String[] { num });
            }
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumberInfoManager removeUserTag error:", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(xyCursor, true);
        }
    }

    public static void removeUserTag(JSONObject numInfoJson) {
        if (numInfoJson != null) {
            numInfoJson.remove(NumberInfo.USER_TAG_KEY);
            numInfoJson.remove(NumberInfo.USER_TAG_TYPE_KEY);
            numInfoJson.remove(NumberInfo.USER_TAG_UPLOAD_STATUS_KEY);
        }
    }

    /**
     * 插入数据
     * 
     * @param num 号码
     * @param result 号码识别结果
     * @param version 版本号
     * @param lastQueryTime 最近一次数据查询时间
     * @return
     */
    public static long insertOrUpdate(String num, JSONObject result, String version, long lastQueryTime) {
        return insertOrUpdate(num, result, version, lastQueryTime, 0);
    }
    
    /*IMOO-20 zhaojiangwei 20161221 start */
    public static long insertOrUpdate(String num, JSONObject result, String version, long lastQueryTime, int flag) {
        if (StringUtils.isNull(num)) {
            return -1;
        }
        XyCursor xyCursor = null;
        try {
            xyCursor = ContactsDBManager.query(TABLE_NAME, new String[] { ID, RESULT }, NUM + " = ? ",
                    new String[] { num });
            String strResult = result == null ? "" : result.toString();
            ContentValues values = BaseManager.getContentValues(null, NUM, num, RESULT, strResult, VERSION,
                    version, LAST_QUERY_TIME, String.valueOf(lastQueryTime), FLAG_T9, String.valueOf(flag));
            if (xyCursor != null && xyCursor.getCount() > 0 && xyCursor.moveToFirst()) {
                String dbResult = xyCursor.getString(xyCursor.getColumnIndex(RESULT));
                // 注意：执行addUserTagToResultIfNeed方法后result可能因添加了用户标记而与一开始有所不同
                strResult = addUserTagToResultIfNeed(result, dbResult);
                values.put(RESULT, strResult);

                if (ContactsDBManager.update(TABLE_NAME, values, NUM + " = ? ", new String[] { num }) > 0) {
                    return xyCursor.getInt(xyCursor.getColumnIndex(ID));
                }
            } else {
                return ContactsDBManager.insert(TABLE_NAME, values);
            }
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumberInfoManager insertOrUpdate error:", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(xyCursor, true);
        }
        return -1;
    }
    /*IMOO-20 zhaojiangwei 20161221 end */

    /**
     * 如果数据库内有本地用户标记且当前号码识别结果内没有用户标记，将本地用户标记添加到当前号码识别结果内
     * 
     * @param result 当前号码识别结果
     * @param dbResult 本地数据库号码识别结果
     * @return 返回原识别结果或添加了用户标记后的识别结果
     * @throws Exception
     */
    private static String addUserTagToResultIfNeed(JSONObject result, String dbResult) throws Exception {
        boolean resultIsNull = result == null;
        // 当前号码识别结果内没有用户标记且本地数据库有用户标记数据时，需要将本地用户标记添加到当前号码识别结果内
        boolean resultHasNoUserTagInfo = (resultIsNull || !result.has(NumberInfo.USER_TAG_KEY));
        boolean localDBHasUserTagInfo = (!StringUtils.isNull(dbResult) && dbResult.contains(NumberInfo.USER_TAG_KEY));
        boolean needAddLocalUserTagToResult = resultHasNoUserTagInfo && localDBHasUserTagInfo;
        if (needAddLocalUserTagToResult) {
            // 联网查询的结果没有本地用户标记，需要补回本地用户标记
            JSONObject resultJson = null;
            if (resultIsNull) {
                resultJson = new JSONObject();
            } else {
                resultJson = result;
            }
            JSONObject userTagDBResultJson = new JSONObject(dbResult);
            resultJson.put(NumberInfo.USER_TAG_KEY, userTagDBResultJson.optString(NumberInfo.USER_TAG_KEY));
            resultJson.put(NumberInfo.USER_TAG_TYPE_KEY, userTagDBResultJson.optInt(NumberInfo.USER_TAG_TYPE_KEY));
            resultJson.put(NumberInfo.USER_TAG_UPLOAD_STATUS_KEY,
                    userTagDBResultJson.optString(NumberInfo.USER_TAG_UPLOAD_STATUS_KEY));
            return resultJson.toString();
        }
        return resultIsNull ? "" : result.toString();
    }

    /**
     * 更新最近一次查询时间
     * 
     * @param num 号码
     * @param lastQueryTime 最近一次数据查询时间
     * @return
     */
    public static int updateLastQueryTime(String num, long lastQueryTime) {
        if (StringUtils.isNull(num)) {
            return -1;
        }
        try {
            return ContactsDBManager.update(TABLE_NAME,
                    BaseManager.getContentValues(null, LAST_QUERY_TIME, String.valueOf(lastQueryTime)), NUM + " = ? ",
                    new String[] { num });
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.e(Constant.TAG, "NumberInfoManager updateLastQueryTime error", e);
            /*SDK-550 hewengao 20160719 end*/
        }
        return -1;
    }

    /**
     * 批量更新最近一次查询时间
     * 
     * @param num 集合号码
     * @param lastQueryTime 最近一次数据查询时间
     * @return
     */
    public static int updateLastQueryTime(Set<String> nums, long lastQueryTime) {
        try {
            int size = nums.size();
            String placeholders = SmsParseRecorder.makePlaceholders(size);
            String whereClause = NUM + " IN(" + placeholders + ")";
            String[] whereArgs = nums.toArray(new String[size]);
            return ContactsDBManager.update(TABLE_NAME,
                    BaseManager.getContentValues(null, LAST_QUERY_TIME, String.valueOf(lastQueryTime)), whereClause,
                    whereArgs);
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.e(Constant.TAG,"NumberInfoManager updateLastQueryTime error:", e);
            /*SDK-550 hewengao 20160719 end*/
        }
        return -1;
    }
    
    
    /**
     * 查询所有支持T9搜索的号码.
     * 
     * @param 
     * @return Cursor
     */
    public static Cursor queryAllT9Numbers(){
        Cursor cursor = null;
        try {
            String whereClause = FLAG_T9 + " = ?";
            String[] whereArgs = new String[] { "1" };;
            XyCursor xyCursor = ContactsDBManager.query(TABLE_NAME, new String[] { ID, NUM, RESULT }, whereClause, whereArgs);
            if (xyCursor!=null) {
                cursor = xyCursor.getCur();
            }
        }
        catch (Throwable e) {
            // TODO: handle exception
        }
        return cursor;
    }
    
    /**
     * 根据号码获取号码识别结果JSON
     * 
     * @param num 号码
     * @return
     */
    public static JSONObject queryNumberInfoByDB(String num) {
        if (StringUtils.isNull(num)) {
            return null;
        }
        // 从数据库中获取陌生来电信息
        NumberInfo numberInfo = queryByNumAndVersion(num, null);
        if (numberInfo == null) {
            return null;
        }
        if (!StringUtils.isNull(numberInfo.result)) {
            try {
                return new JSONObject(numberInfo.result);
            } catch (Throwable e) {
                /*SDK-550 hewengao 20160719 start*/
                LogManager.w(Constant.TAG, "NumberInfoManager queryNumberInfoByDB error:", e);
                /*SDK-550 hewengao 20160719 end*/
            }
        }
        return null;
    }

    /**
     * 根据号码及版本号获取号码信息，没有版本号时可传null
     * 
     * @param num 号码
     * @param version 版本号
     * @return
     */
    public static NumberInfo queryByNumAndVersion(String num, String version) {
        if (StringUtils.isNull(num)) {
            return null;
        }

        String whereClause = null;
        String[] whereArgs = null;
        if (StringUtils.isNull(version)) {
            whereClause = NUM + " = ?";
            whereArgs = new String[] { num };
        } else {
            whereClause = NUM + " = ? AND " + VERSION + " = ?";
            whereArgs = new String[] { num, version };
        }
        // 从数据库中查找对应号码数据
        List<NumberInfo> dataList = query(whereClause, whereArgs, 1);
        return (dataList == null || dataList.size() < 1) ? null : dataList.get(0);
    }

    /**
     * 根据号码获取号码信息
     * 
     * @param num 号码
     * @param limit 获取的最大数据数量
     * @return
     */
    private static List<NumberInfo> queryByNums(List<String> nums) {
        int size = nums.size();
        String placeholders = SmsParseRecorder.makePlaceholders(size);
        String whereClause = NUM + " IN(" + placeholders + ")";
        String[] whereArgs = nums.toArray(new String[size]);
        return query(whereClause, whereArgs, Integer.MAX_VALUE);
    }

    /**
     * 根据查询条件获取数据
     * 
     * @param whereClause
     * @param whereArgs
     * @param limit
     * @return
     */
    private static List<NumberInfo> query(String whereClause, String[] whereArgs, int limit) {
        XyCursor xyCursor = null;
        try {
            xyCursor = ContactsDBManager.query(false, TABLE_NAME, new String[] { ID, NUM, RESULT, VERSION,
                    LAST_QUERY_TIME }, whereClause, whereArgs, null, null, null, String.valueOf(limit));

            if (xyCursor == null || xyCursor.getCount() == 0) {
                return null;
            }
            List<NumberInfo> dataList = new ArrayList<NumberInfo>();
            NumberInfo data = null;
            while (xyCursor.moveToNext()) {
                data = new NumberInfo();
                data.id = xyCursor.getInt(xyCursor.getColumnIndex(ID));
                data.num = xyCursor.getString(xyCursor.getColumnIndex(NUM));
                data.result = xyCursor.getString(xyCursor.getColumnIndex(RESULT));
                data.version = xyCursor.getString(xyCursor.getColumnIndex(VERSION));
                data.lastQueryTime = xyCursor.getLong(xyCursor.getColumnIndex(LAST_QUERY_TIME));
                dataList.add(data);
            }
            return dataList;
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumberInfoManager query error:", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(xyCursor, true);
        }
        return null;
    }

    /**
     * 获取需要重新识别的号码信息
     * 
     * @param type 
     *            NumberInfoManager.TYPE_REPARSE_NO_NETWORK_NUM_INFO:重新识别未联网导致无法查询到号码信息的号码
     *            NumberInfoManager.TYPE_REPARSE_INVALID_NUM_INFO:重新识别已联网查询过但无号码信息的号码(相同号码24小时内只会重新识别一次)
     *            NumberInfoManager.TYPE_REPARSE_EXPIRED_NUM_INFO:重新识别已过有效周期的号码信息(有效周期30天)
     * @param limit
     * @return
     */
    public static Map<String, String> needReparseNumInfo(int type, int limit) {
        Map<String, String> needReparseNumInfoMap = new LinkedHashMap<String, String>();
        XyCursor xyCursor = null;
        try {

            String whereClause = null;
            switch (type) {
            case TYPE_REPARSE_NO_NETWORK_NUM_INFO:
                whereClause = RESULT + "='' AND " + LAST_QUERY_TIME + " > 0";
                break;
            case TYPE_REPARSE_INVALID_NUM_INFO:
                whereClause = RESULT
                        + "<>'' AND "
                        + VERSION
                        + "='' AND "
                        + LAST_QUERY_TIME
                        + ">0 AND "
                        + LAST_QUERY_TIME
                        + " <= "
                        + (System.currentTimeMillis() - DexUtil.getUpdateCycleByType(
                                OnlineUpdateCycleConfigInterface.TYPE_QUERY_CALLS_NUMBER_INFO_CYCLE, Constant.DAY));
                break;
            case TYPE_REPARSE_EXPIRED_NUM_INFO:
                whereClause = RESULT
                        + "<>'' AND "
                        + VERSION
                        + "<>'' AND "
                        + LAST_QUERY_TIME
                        + ">0 AND "
                        + LAST_QUERY_TIME
                        + " <= "
                        + (System.currentTimeMillis() - DexUtil
                                .getUpdateCycleByType(
                                        OnlineUpdateCycleConfigInterface.TYPE_CALLS_NUMBER_INFO_EFFECTIVE_CYCLE,
                                        Constant.month));
                break;
            default:
                return null;
            }
            xyCursor = ContactsDBManager.query(false, TABLE_NAME, new String[] { NUM, VERSION }, whereClause, null,
                    null, null, LAST_QUERY_TIME + " DESC", String.valueOf(limit));

            if (xyCursor == null || xyCursor.getCount() == 0) {
                return null;
            }
            while (xyCursor.moveToNext()) {
                String num = xyCursor.getString(xyCursor.getColumnIndex(NUM));
                String version = xyCursor.getString(xyCursor.getColumnIndex(VERSION));
                needReparseNumInfoMap.put(num, version);
            }
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumberInfoManager needReparseNumInfo error:", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(xyCursor, true);
        }
        return needReparseNumInfoMap;
    }

    /**
     * 获取需要上传的用户标记信息
     * 
     * @param limit
     * @return
     */
    public static Map<String, String[]> needUploadUserTagInfo(int limit) {
        Map<String, String[]> needUploadUserTagInfoMap = new LinkedHashMap<String, String[]>();
        XyCursor xyCursor = null;
        try {
            String whereClause = RESULT + " LIKE '%\"" + NumberInfo.USER_TAG_UPLOAD_STATUS_KEY + "\":"
                    + NumberInfo.UPLOAD_STATUS_NO_UPLOAD + "%' AND " + LAST_QUERY_TIME + ">0 ";
            xyCursor = ContactsDBManager.query(false, TABLE_NAME, new String[] { NUM, RESULT }, whereClause, null,
                    null, null, LAST_QUERY_TIME + " DESC", String.valueOf(limit));

            if (xyCursor == null || xyCursor.getCount() == 0) {
                return null;
            }
            while (xyCursor.moveToNext()) {
                String num = xyCursor.getString(xyCursor.getColumnIndex(NUM));
                String result = xyCursor.getString(xyCursor.getColumnIndex(RESULT));
                JSONObject resultJson = new JSONObject(result);
                needUploadUserTagInfoMap.put(num, new String[] { resultJson.optString(NumberInfo.USER_TAG_KEY),
                        resultJson.optString(NumberInfo.USER_TAG_TYPE_KEY) });
            }
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumberInfoManager needUploadUserTagInfo error:", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(xyCursor, true);
        }
        return needUploadUserTagInfoMap;
    }

    /**
     * 是否有效号码数据，存在号码及版本号的数据为有效数据，如果存在用户标记的也属于有效数据
     * 
     * @param numberInfo
     * @return true:有效数据 false:无效数据
     */
    public static boolean isEffectiveData(JSONObject numberInfo) {
        if (numberInfo == null) {
            return false;
        }
        boolean isEffective = !StringUtils.isNull(numberInfo.optString(NumberInfo.NUM_KEY))
                && !StringUtils.isNull(numberInfo.optString(NumberInfo.VERSION_KEY));
        boolean hasUserTag = !StringUtils.isNull(numberInfo.optString(NumberInfo.USER_TAG_KEY));
        return isEffective || hasUserTag;
    }
}
/* SDK-428 huangzhiqiang 20160618 end */
